package com.gitee.feizns.dynamic.bean;

import java.util.Map;
import java.util.function.Function;

/**
 * <b>可转换的对象，表明实现该接口的类具有javabean的相互转换功能</b>
 * <pre>{@code
 *  @Data
 *  static class User implements Convertible {
 *      private Integer id;
 *      private String name;
 *  }
 *  public static void main(String[] args) {
 *      User user = new User(12, "张三");
 *      Admin admin = user.to(Admin.class); //新建一个Admin对象并将user中的值复制过去
 *      System.out.println(admin);          //Admin{id=12,name="张三"}
 *      user.setId(15);
 *      user.setName("李四");
 *      user.to(admin);
 *      System.out.println(admin);          //Admin{id=15,name="李四"}
 *  }
 * }</pre>
 * @author feizns
 * @since 2019/6/9 0009
 */
public interface Convertible extends PropertiesIterable<Convertible> {

    /**
     * <b>新建一个targetType类型的对象，并将当前对象的属性复制其中</b>
     * <pre>{@code
     *  User user = new User(12, "张三");
     *  Admin admin = user.to(Admin.class);
     *  System.out.println(admin);  //Admin{id=12,name="张三"}
     * }</pre>
     * @param targetType 目标类型
     * @return 目标类型对象
     */
    default <T> T to(Class<T> targetType) {
        return BeanUtils.to(this, targetType);
    }

    /**
     * <b>新建一个targetType类型的对象，并将当前对象的属性复制其中</b>
     * <pre>{@code
     *  User user = new User(12, "张三");
     *  Admin admin = user.copyPropertiesTo(Admin.class);
     *  System.out.println(admin);  //Admin{id=12,name="张三"}
     * }</pre>
     * @see #to(Class)
     * @param targetType 目标类型
     * @return 目标类型对象
     */
    default <T> T copyPropertiesTo(Class<T> targetType) {
        return BeanUtils.copyProperties(targetType, this);
    }

    /**
     * <b>指定映射属性规则的同时、新建一个targetType类型的对象，并将当前对象的属性复制其中</b>
     * @param targetType 目标对象类型
     * @return 期望得到的类型
     */
    default <T> T copyPropertiesTo(Class<T> targetType, Function<String, String> popsMap) {
        return BeanUtils.copyProperties(targetType, popsMap, this);
    }

    /**
     * <b>将当前对象的属性赋值给其他对象</b>
     * @param target 赋值的目标对象
     * @param <T> 目标类型
     * @return 目标对象
     */
    default <T> T copyPropertiesTo(T target) {
        return BeanUtils.copyProperties(target, this);
    }

    /**
     * <b>将当前对象的属性赋值给其他对象</b>
     * <p>
     *     并指定属性映射规则
     * </p>
     * @param target 目标对象
     * @return 期望赋值给的目标对象
     */
    default <T> T copyPropertiesTo(T target, Function<String, String> popsMap) {
        return BeanUtils.copyProperties(target, popsMap, this);
    }

    /**
     * <b>将当前实体转换为Map</b>
     * <pre>{@code
     *  User user = new User().setId(12).setName("zhangSan");
     *  Map<String, Object> map = user.toMap();
     *  //{id=12,name="zhangSan"}
     *  System.out.println(map);
     * }</pre>
     * @see BeanUtils#toMap(Object)
     * @return {@link java.util.Map}
     */
    default Map<String, Object> toMap() {
        return BeanUtils.toMap(this);
    }

    /**
     * <b>将source中的属性复制到当前对象中（如果source是一个Map对象讲引用对应键值的值）</b>
     * <pre>{@code
     *  UserDto userDto = new UserDto().setId(12).setName("zhangSan");
     *  User user = new User();
     *  user.from(userDto);
     *  //User(id=12,name="zhangSan")
     *  System.out.println(user);
     * }</pre>
     * <pre>{@code
     *  //对于Map的情况
     *  Map<String, Object> map = new HashMap<String, Object>();
     *  map.put("id", 12);
     *  map.put("name", "zhangSan");
     *  User user = new User();
     *  user.from(map);
     *  //User(id=12,name="zhangSan")
     *  System.out.println(user);
     * }</pre>
     * @param source 实体
     */
    default void from(Object source) {
        BeanUtils.copyProperties(this, source);
    }

}
